import re

from django import http
from django.contrib.auth import login
from django.shortcuts import render, redirect

# Create your views here.
# 实现QQ按钮的跳转
from django.urls import reverse
from django.views import View
from QQLoginTool.QQtool import OAuthQQ
from django_redis import get_redis_connection
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

from apps.oauth.models import OAuthQQUser
from apps.oauth.utils import generate_access_token, check_access_token
from apps.users.models import User
from meiduomall import settings

"""
1、实现QQ按钮的跳转
    ① 直接把拼接好的URL放到A标签上
    ② 让前端发个ajax请求
https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101518219&redirect_uri=http://www.meiduo.site:8000/oauth_callback&state=test
"""


# 实现QQ按钮的跳转
class OauthQQURLView(View):
    def get(self, request):
        # 1、创建实例对象
        state = 'test'
        qqoauth = OAuthQQ(
            client_secret=settings.QQ_CLIENT_SECRET,
            client_id=settings.QQ_CLIENT_ID,
            redirect_uri=settings.QQ_REDIRECT_URI,
            state=state,
        )
        # 2、调用方法
        login_url = qqoauth.get_qq_url()

        return http.JsonResponse({'login_url': login_url})


"""
一、写下需求（前端要做什么，后端要做什么）
    前端需要把用户同意的code（code是腾讯认证服务器返回的）提交给后端
    后端需要通过code换取token
二、大体思路（后端的大体思路）
    1、获取code
    2、通过读取文档将code转换为token
三、把详细思路完善下（纯后端）
    1、获取code
    2、通过读取文档将code转换为token
四、确定我们的请求方式和路由
    GET oauth_callback
"""


# 跳转之后的认证
class OauthQQUserView(View):
    def get(self, requset):
        # 1、获取code
        code = requset.GET.get('code')
        if code is None:
            return render(requset, 'oauth_callback.html', context={'errmsg': '没有获取到指定的参数'})
        # 2、通过读取文档将code转换为token
        qqoauth = OAuthQQ(
            client_secret=settings.QQ_CLIENT_SECRET,
            client_id=settings.QQ_CLIENT_ID,
            redirect_uri=settings.QQ_REDIRECT_URI,
        )
        token = qqoauth.get_access_token(code)
        # 3、通过token换取openid
        openid = qqoauth.get_open_id(token)
        # 4、根据openid进行数据查询
        try:
            qquser = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 如果有相同的openid 则说明用户绑定过

            # 对openid进行加密
            openid_access_token = generate_access_token(openid)
            return render(requset, 'oauth_callback.html', context={'openid_access_token': openid_access_token})
            # 对openid进行加密

        else:
            # 如果没有相同的openid 则说明用户没有绑定过
            response = redirect(reverse('contents:index'))

            # 设置登录状态
            login(requset, qquser.user)
            # 设置cookie信息
            response.set_cookie('username', qquser.user.username, max_age=14 * 24 * 3600)

            return response

        return render(requset, 'oauth_callback.html')

    # 通过post方式来绑定用户
    def post(self, request):
        # 1、接收数据
        data = request.POST

        # 2、获取书籍
        mobile = data.get('mobile')
        password = data.get('pwd')
        sms_code = data.get('sms_code')
        access_token = data.get('access_token')

        # 3、验证数据
        # 3.1判断参数是否齐全
        if not all([mobile, password, sms_code]):
            return http.HttpResponseBadRequest('缺少必传参数')
        # 3.2判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseBadRequest('请输入正确的手机号码')
        # 3.3判断密码是否合格
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseBadRequest('请输入8-20位的密码')
        # 3.4判断短信验证码是否一致
        redis_conn = get_redis_connection('code')
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        if sms_code_server is None:
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '无效的短信验证码'})
        if sms_code != sms_code_server.decode():
            return render(request, 'oauth_callback.html', {'sms_code_errmsg': '输入短信验证码有误'})

        # 4、access_token(加密后的openid)解密
        openid = check_access_token(access_token)

        # 5、根据手机号进行用户信息判断

        try:
            # 如果此手机号之前没有注册过，则重新创建用户
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            User.objects.create_user(
                username=mobile,
                password=password,
                mobile=mobile
            )
        else:
            # 如果此手机号之前注册过，绑定前要验证码
            if not user.check_password(password):
                return http.HttpResponseBadRequest('密码错误')
        # 则和用户进行绑定，
        qquser = OAuthQQUser.objects.create(
            user=user,
            openid=openid
        )
        # 6、设置登录状态
        login(request, user)
        # 7、设置cookie信息
        response = redirect(reverse('contents:index'))
        response.set_cookie('username', user.username, max_age=14*24*3600)
        # 跳转指定页面
        return response








































# # itsdangerous的使用
# # 一、加密
# # 创建实例对象
# # secret_key    秘钥  习惯上我们使用settings.secret_key
# # expires_in    过期时间 单位：s
# s = Serializer(secret_key=settings.SECRET_KEY, expires_in=3600)
# # 组织要加密的数据
# script = {
#     'openid': '1234'
# }
# # 加密
# s.dumps(script)
# # b'eyJhbGciOiJIUzUxMiIsImlhdCI6MTYxMjEwMjAxNCwiZXhwIjoxNjEyMTA1NjE0fQ.
# # eyJvcGVuaWQiOiIxMjM0In0.
# # 3Q9dPJYs9DiwgAK7TpMzuh6SIeUM_Nbn9Y55kYsnOndptg99aQOFj76VWGkLqzbu6K4Kqjy_Qjor1ZPifhnX9A'
#
# # 二、解密
# s = Serializer(secret_key=settings.SECRET_KEY, expires_in=3600)
# s.loads(
#     'eyJhbGciOiJIUzUxMiIsImlhdCI6MTYxMjEwMjAxNCwiZXhwIjoxNjEyMTA1NjE0fQ.eyJvcGVuaWQiOiIxMjM0In0.3Q9dPJYs9DiwgAK7TpMzuh6SIeUM_Nbn9Y55kYsnOndptg99aQOFj76VWGkLqzbu6K4Kqjy_Qjor1ZPifhnX9A')
